﻿Imports System.Text
Imports System.Collections.Specialized
Imports System.IO
Imports System.Windows
Imports Microsoft.VisualStudio.Text.Formatting
Imports System.Globalization
Imports Microsoft.VisualStudio.Text.Editor.DragDrop

Namespace Microsoft.VisualStudio.ImageInsertion
	''' <summary>
	''' Handles a drag and drop of an image onto the editor.
	''' The image came from the file system (FileDrop) or from the VS Solution Explorer.
	''' </summary>
	Friend Class ImageInsertionDropHandler
		Implements IDropHandler
		Private manager As ImageAdornmentManager
		Private ReadOnly SupportedImageExtensions As New List(Of String) From {".jpg", ".jpeg", ".bmp", ".png", ".gif"}

		Friend Sub New(ByVal manager As ImageAdornmentManager)
			Me.manager = manager
		End Sub

		''' <summary>
		''' See <see cref="IDropHandler.HandleDragStarted"/> for more information.
		''' </summary>
		''' <param name="dragDropInfo"></param>
		''' <returns></returns>
		Public Function HandleDragStarted(ByVal dragDropInfo As DragDropInfo) As DragDropPointerEffects Implements IDropHandler.HandleDragStarted
			'drag started, so create a new Bitmap to be shown to the user as visual feedback
			Dim imageFilename = GetImageFilename(dragDropInfo)

			Me.manager.PreviewImageAdornment.Show(imageFilename)

			'show the copy cursor to the user
			Return DragDropPointerEffects.Copy
		End Function

		''' <summary>
		''' See <see cref="IDropHandler.HandleDraggingOver"/> for more information.
		''' </summary>
		''' <param name="dragDropInfo"></param>
		''' <returns></returns>
		Public Function HandleDraggingOver(ByVal dragDropInfo As DragDropInfo) As DragDropPointerEffects Implements IDropHandler.HandleDraggingOver
			Me.manager.PreviewImageAdornment.MoveTo(dragDropInfo.Location)

			Dim targetLine = Me.manager.GetTargetTextViewLine(Me.manager.PreviewImageAdornment.VisualElement)
			If targetLine IsNot Nothing AndAlso targetLine.Length > 0 Then
				Me.manager.HighlightLineAdornment.Highlight(targetLine)
				Return DragDropPointerEffects.Copy
			Else
				Me.manager.HighlightLineAdornment.Clear()
				Return DragDropPointerEffects.None
			End If
		End Function

		Private Sub RemovePreviewImage()
			Me.manager.PreviewImageAdornment.Clear()
			Me.manager.HighlightLineAdornment.Clear()
		End Sub

		''' <summary>
		''' See <see cref="IDropHandler.HandleDataDropped"/> for more information.
		''' </summary>
		''' <param name="dragDropInfo"></param>
		''' <returns></returns>
		Public Function HandleDataDropped(ByVal dragDropInfo As DragDropInfo) As DragDropPointerEffects Implements IDropHandler.HandleDataDropped
			Try
				manager.AddImageAdornment(manager.PreviewImageAdornment.VisualElement)
				Return DragDropPointerEffects.Copy
			Finally
				RemovePreviewImage()
			End Try
		End Function

		''' <summary>
		''' See <see cref="IDropHandler.IsDropEnabled"/> for more information.
		''' </summary>
		''' <param name="dragDropInfo"></param>
		''' <returns></returns>
		Public Function IsDropEnabled(ByVal dragDropInfo As DragDropInfo) As Boolean Implements IDropHandler.IsDropEnabled
			Dim result = False

			Dim imageFilename = GetImageFilename(dragDropInfo)

			If Not String.IsNullOrEmpty(imageFilename) Then
				Dim imageFileExtension = Path.GetExtension(imageFilename).ToLowerInvariant()
				result = Me.SupportedImageExtensions.Contains(imageFileExtension)
			End If

			If Not result Then
				RemovePreviewImage()
			End If

			Return result
		End Function

		Private Shared Function GetImageFilename(ByVal info As DragDropInfo) As String
			Dim data As New DataObject(info.Data)

			If info.Data.GetDataPresent(ImageInsertionDropHandlerProvider.FileDropDataFormat) Then
				' The drag and drop operation came from the file system
				Dim files = data.GetFileDropList()

				If files IsNot Nothing AndAlso files.Count = 1 Then
					Return files(0)
				End If
			ElseIf info.Data.GetDataPresent(ImageInsertionDropHandlerProvider.VSProjectItemDataFormat) Then
				' The drag and drop operation came from the VS solution explorer
				Return data.GetText()
			End If

			Return Nothing
		End Function

		''' <summary>
		''' See <see cref="IDropHandler.HandleDragCanceled"/> for more information.
		''' </summary>
		Public Sub HandleDragCancelled() Implements IDropHandler.HandleDragCanceled
			Me.manager.PreviewImageAdornment.Clear()
			Me.manager.HighlightLineAdornment.Clear()
		End Sub
	End Class
End Namespace